package gis.dao;

import bean.common.*;
import gis.algorithm.Extent;
import gis.algorithm.cluster.ClusterArg;
import gis.algorithm.cluster.ClusterCalculator;
import gis.algorithm.cluster.ClusterPoint;
import gis.algorithm.cluster.RqCluster;
import gis.common.GisConfig;
import gis.common.ServiceFactory;
import gis.service.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cache.DataCache;

public class ResCellDao {

    /**
     * 得到4G小区
     *
     * @param rqCell
     * @return
     * @throws Exception
     */
    public List<Cell> GetLTECells(RqCell rqCell) throws Exception {
        List<Cell> list = new ArrayList<Cell>();
        if (rqCell.isLTE() == false) {
            return list;
        }

        ResCellService dao = ServiceFactory.getInstance(ResCellService.class);
        list = dao.GetLTECells(rqCell);
        return list;
    }

    /**
     * 得到3G小区
     *
     * @param rqCell
     * @return
     * @throws Exception
     */
    public List<Cell> GetTDCells(RqCell rqCell) throws Exception {
        List<Cell> list = new ArrayList<Cell>();
        if (rqCell.isTD() == false) {
            return list;
        }

        ResCellService dao = ServiceFactory.getInstance(ResCellService.class);
        list = dao.GetTDCells(rqCell);

        return list;
    }

    /**
     * 得到2G小区
     *
     * @param rqCell
     * @return
     * @throws Exception
     */
    public List<Cell> GetGSMCells(RqCell rqCell) throws Exception {
        List<Cell> list = new ArrayList<Cell>();
        if (rqCell.isGSM() == false) {
            return list;
        }

        ResCellService dao = ServiceFactory.getInstance(ResCellService.class);
        list = dao.GetGSMCells(rqCell);

        return list;
    }

    /**
     * 获取小区信息
     *
     * @param rqCell
     * @return
     * @throws Exception
     */
    public List<Cell> GetResCells(RqCell rqCell) throws Exception {
        List<Cell> list = new ArrayList<Cell>();
        if (rqCell.isLTE()) {
            List<Cell> ltes = GetLTECells(rqCell);
            list.addAll(ltes);
        }
        if (rqCell.isTD()) {
            List<Cell> tds = GetTDCells(rqCell);
            list.addAll(tds);
        }
        if (rqCell.isGSM()) {
            List<Cell> gsms = GetGSMCells(rqCell);
            list.addAll(gsms);
        }
        return list;

    }

    /**
     * 得到基站
     *
     * @param rqCell
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public List<Bts> GetBtsList(RqCell rqCell) throws Exception {
        List<Bts> list = new ArrayList<Bts>();
        String keyString = "ResCellDao_GetStationList" + ResCellService.GetKeyPara(rqCell);
        long time = 1000 * 60 * 10;
        List<Bts> bts = null;

        if (rqCell.isLTE()) {
            Object object = DataCache.getData(keyString + "_isLTE");
            if (object != null) {
                bts = (List<Bts>) object;
            }
            if (bts == null) {
                bts = CreateBtsList(GetLTECells(rqCell));
                DataCache.addData(keyString + "_isLTE", bts, time);
            }
            list.addAll(bts);
        }

        bts = null;
        if (rqCell.isGSM()) {
            Object object = DataCache.getData(keyString + "_isGSM");
            if (object != null) {
                bts = (List<Bts>) object;
            }
            if (bts == null) {
                bts = CreateBtsList(GetGSMCells(rqCell));
                DataCache.addData(keyString + "_isGSM", bts, time);
            }
            list.addAll(bts);
        }

        bts = null;
        if (rqCell.isTD()) {
            Object object = DataCache.getData(keyString + "_isTD");
            if (object != null) {
                bts = (List<Bts>) object;
            }
            if (bts == null) {
                bts = CreateBtsList(GetTDCells(rqCell));
                DataCache.addData(keyString + "_isTD", bts, time);
            }
            list.addAll(bts);
        }

        return list;
    }

    /**
     * 得到基站
     *
     * @param rqCell
     * @param rqCluster
     * @return
     * @throws Exception
     */
    public List<Bts> GetBtsList(RqCell rqCell, RqCluster rqCluster) throws Exception {
        List<Bts> bts = GetBtsList(rqCell);
        bts = ClusterBts(bts, rqCluster);

        return bts;
    }



    /**
     * 获取边界内的小区
     */
    public List<Cell> GetExtendCells(List<Cell> cells, RqCluster rqCluster) {
        List<Cell> list = new ArrayList<Cell>();

        // 得到当前可视区域内的小区
        for (Cell b : cells) {
            if (b.getLongitude() > rqCluster.getxMax() || b.getLongitude() < rqCluster.getxMin() || b.getLatitude() > rqCluster.getyMax() || b.getLatitude() < rqCluster.getyMin()) {
                continue;
            } else {
                list.add(b);
            }
        }
        return list;
    }

    /**
     * 聚合小区
     *
     * @param cells
     * @param rqCluster
     * @return
     */
    public List<Cell> clusterCells(List<Cell> cells, RqCluster rqCluster) {
        List<Cell> list = new ArrayList<Cell>();
        List<ClusterArg<Cell>> clusterArgs = new ArrayList<ClusterArg<Cell>>();
        GisConfig con = GisConfig.GetInstance();

        // 得到当前可视区域内的小区
        for (Cell b : cells) {
            if (b.getLongitude() > rqCluster.getxMax() || b.getLongitude() < rqCluster.getxMin() || b.getLatitude() > rqCluster.getyMax() || b.getLatitude() < rqCluster.getyMin()) {
                continue;
            } else {
                list.add(b);
                ClusterArg<Cell> arg = new ClusterArg<Cell>();
                arg.setX(b.getLongitude());
                arg.setY(b.getLatitude());
                arg.setObj(b);
                clusterArgs.add(arg);
            }
        }

        if (list.size() > 500 && rqCluster.getLevel() + 2 < con.getMapmaxlevel()) {
            // 进行汇聚
            ClusterCalculator c = ClusterCalculator.getInstance();

            List<ClusterPoint<Cell>> result = c.calc(clusterArgs, rqCluster);
            list.clear();
            for (ClusterPoint<Cell> r : result) {
                Cell first = r.getObjs().get(0);

                Cell b = new Cell(first.getResType());
                b.setValue(r.getCount());
                b.setLongitude(r.getX());
                b.setLatitude(r.getY());
                b.setTag("cluster");

                list.add(b);
            }
        }
        clusterArgs.clear();

        return list;
    }

    /**
     * 将小区归属到基站上
     *
     * @param cells
     * @return
     */
    public List<Bts> CreateBtsList(List<Cell> cells) {
        Map<String, Bts> map = new HashMap<String, Bts>();
        Bts bts;
        for (Cell cell : cells) {
            if (!map.containsKey(cell.getBtsId())) {
                bts = new Bts(cell.getResType());
                map.put(cell.getBtsId(), bts);

                bts.setId(cell.getBtsId());
                bts.setName(cell.getBtsName());
                bts.setOriginalLatitude(cell.getOriginalLatitude());
                bts.setOriginalLongitude(cell.getOriginalLongitude());
                bts.setLatitude(cell.getLatitude());
                bts.setLongitude(cell.getLongitude());
                bts.setCityId(cell.getCityId());
                bts.setCityName(cell.getCityName());
                bts.setCountryId(cell.getCountryId());
                bts.setCountyName(cell.getCountyName());
            }
            map.get(cell.getBtsId()).getCells().add(cell);
        }
        List<Bts> list = new ArrayList<Bts>();
        for (String key : map.keySet()) {
            list.add(map.get(key));
        }

        return list;
    }

    /**
     * 聚合资源
     *
     * @param bts       基站
     * @param rqCluster 聚合参数
     * @return
     */
    public static List<Bts> ClusterBts(List<Bts> bts, RqCluster rqCluster) {
        List<Bts> list = new ArrayList<Bts>();
        List<ClusterArg<Bts>> clusterArgs = new ArrayList<ClusterArg<Bts>>();
        GisConfig con = GisConfig.GetInstance();
        // 得到当前可视区域内的基站
        for (Bts b : bts) {
            if (b.getLongitude() > rqCluster.getxMax() || b.getLongitude() < rqCluster.getxMin() || b.getLatitude() > rqCluster.getyMax() || b.getLatitude() < rqCluster.getyMin()) {
                continue;
            } else {
                list.add(b);
                ClusterArg<Bts> arg = new ClusterArg<Bts>();
                arg.setX(b.getLongitude());
                arg.setY(b.getLatitude());
                arg.setObj(b);
                clusterArgs.add(arg);
            }
        }

        if (list.size() > 1000 && rqCluster.getLevel() + 2 < con.getMapmaxlevel()) {
            // 进行汇聚
            ClusterCalculator c = ClusterCalculator.getInstance();

            List<ClusterPoint<Bts>> result = c.calc(clusterArgs, rqCluster, 80);
            list.clear();
            for (ClusterPoint<Bts> r : result) {
                Bts first = r.getObjs().get(0);

                Bts b = new Bts(first.getResType());
                b.setValue(r.getCount());
                b.setLongitude(r.getX());
                b.setLatitude(r.getY());
                b.setTag("cluster");

                list.add(b);
            }
        }
        clusterArgs.clear();

        return list;

    }

    /**
     * 获取边界内的小区
     */
    public static List<Bts> GetExtendBts(List<Bts> btses, RqCluster rqCluster) {
        List<Bts> list = new ArrayList<Bts>();
        double xmax = 0.0, xmin = 0.0, ymax = 0.0, ymin = 0.0;

        // 得到当前可视区域内的小区
        for (Bts b : btses) {
            if (b.getLongitude() > rqCluster.getxMax() || b.getLongitude() < rqCluster.getxMin() || b.getLatitude() > rqCluster.getyMax() || b.getLatitude() < rqCluster.getyMin()) {
                continue;
            } else {
                list.add(b);
            }
        }
        return list;
    }

    /**
     * 将小区归属到基站上
     *
     * @param cells
     * @return
     */
    public static <E> List<Bts> GetBtsFromCell(List<E> cells) {
        Map<String, Bts> map = new HashMap<String, Bts>();
        Bts bts;
        for (int i = 0; i < cells.size(); i++) {
            Cell cell = (Cell) cells.get(i);
            if (!map.containsKey(cell.getBtsId())) {
                bts = new Bts(cell.getResType());
                map.put(cell.getBtsId(), bts);

                bts.setId(cell.getBtsId());
                bts.setName(cell.getBtsName());
                bts.setOriginalLatitude(cell.getOriginalLatitude());
                bts.setOriginalLongitude(cell.getOriginalLongitude());
                bts.setLatitude(cell.getLatitude());
                bts.setLongitude(cell.getLongitude());
                bts.setCityId(cell.getCityId());
                bts.setCityName(cell.getCityName());
                bts.setCountryId(cell.getCountryId());
                bts.setCountyName(cell.getCountyName());
            }
            map.get(cell.getBtsId()).getCells().add(cell);
        }
        List<Bts> list = new ArrayList<Bts>();
        for (String key : map.keySet()) {
            list.add(map.get(key));
        }

        return list;
    }
}
